package com.stoney.handler;

import com.stoney.cache.DefaultSpiderCache;
import com.stoney.listeners.TakeUrlListener;
import com.stoney.spider.SpiderConfig;
import com.stoney.utils.FilesUtil;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;



/**
 * Created by Stony on 2015/11/24.
 */
public class SpiderResourceHandler extends SpiderAbstractHandler implements TakeUrlListener {

    private String save_dir;
    private String math_url;
    private String base_url;
    private String index_url;

    private final static  org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(DefaultSpiderCache.class);
    public void print(String format,Object...agrs){
        logger.info(String.format(format,agrs));
    }

    public static ThreadLocal<ArrayBlockingQueue> localQueue = new ThreadLocal<ArrayBlockingQueue>();
    @Override
    public void initQueue(){
//        mediaQueue = new ArrayBlockingQueue(20000);
//        pageQueue = new ArrayBlockingQueue(20000);
        //repeatQueue = new ArrayBlockingQueue(20000);
//        cssQueue = new ArrayBlockingQueue(20000);
        spiderResourceQueue = new ArrayBlockingQueue<SpiderResource>(30000);
        localQueue.set(spiderResourceQueue);
    }
    @Override
    public void initConfig() {
        setCache(new DefaultSpiderCache());
        save_dir = SpiderConfig.getSaveDir();
        base_url = SpiderConfig.getBaseURL();
        index_url = SpiderConfig.getIndexURL();
        math_url = SpiderConfig.getMatchUrl();
        print("#initConfig#\n<save_dir = %s>\n<base_url = %s>\n<index_url = %s>\n<math_url = %s>\n",
                save_dir,base_url,index_url,math_url);
    }

    @Override
    public void run() {
        process(index_url);
    }

    @Override
    public String getSaveDir() {
        return this.save_dir;
    }

    @Override
    public String getMathUrl() {
        return this.math_url;
    }

    @Override
    public String getBaseUrl() {
        return this.base_url;
    }

    @Override
    public ArrayBlockingQueue getSpiderResourceQueue() {
        return this.spiderResourceQueue;
    }

    @Override
    protected void startWork() {
//        service.execute(new ProcessTask(this,pageQueue,1));
        //service.execute(new ProcessTask(this,mediaQueue,2));
        //service.execute(new ProcessTask(this,cssQueue,3));
        for(int i = 0; i < Runtime.getRuntime().availableProcessors(); i++) {
            service.execute(new ProcessResourceTask2(spiderResourceQueue, this));
        }
        service.shutdown();
    }

    @Override
    public void takeUrl(SpiderResource re) {
        if(FilesUtil.isNotEmpty(re.url)){
            if(!containsCache(re.url)){
                if(re.type == SpiderResource.SpiderResourceType.HTML){
                    parsePage(re.url);
                }
                else if(re.type == SpiderResource.SpiderResourceType.CSS){
                    parseCss(re.url);
                }
                else {
                    parseMedia(re.url);
                }

            }
        }
    }
    /**
     *
     * @param url
     * @param type page=1,media=2,css=3
     */
    @Override
    public void takeUrl(String url,int type) {
        if(!containsCache(url)){
            if(type == 1){
                parsePage(url);
            }
            if(type == 2){
                parseMedia(url);
            }
            if(type == 3){
                parseCss(url);
            }
        }
    }
    private static class ProcessResourceTask2 implements Runnable{
        private BlockingQueue<SpiderResource> queue;
        private SpiderResourceHandler handler;

        private ProcessResourceTask2(BlockingQueue<SpiderResource> queue, SpiderResourceHandler handler) {
            super();
            this.queue = queue;
            this.handler = handler;
        }

        @Override
        public void run() {
            try {
                while(true){
                    SpiderResource re = queue.take();
                    if(re != null) {
                        new SpiderHandlerSupport(handler).processUrl(re);
                        //listener.takeUrl(re);
                    }
                }
            } catch (InterruptedException e) {
                logger.error("ProcessResourceTask Error.",e);
            }
        }
    }
    private static class ProcessResourceTask implements Runnable{
        private BlockingQueue<SpiderResource> queue;
        private TakeUrlListener listener;

        private ProcessResourceTask(BlockingQueue<SpiderResource> queue, TakeUrlListener listener) {
            super();
            this.queue = queue;
            this.listener = listener;
        }

        @Override
        public void run() {
            try {
                while(true){
                    SpiderResource re = queue.take();
                    if(re != null) listener.takeUrl(re);
                }
            } catch (InterruptedException e) {
                logger.error("ProcessResourceTask Error.",e);
            }
        }
    }
    private static class ProcessTask implements Runnable{
        private BlockingQueue<String> queue;
        private TakeUrlListener listener;
        private int type;
        public ProcessTask(TakeUrlListener listener,BlockingQueue<String> queue,int type) {
            super();
            this.listener = listener;
            this.queue = queue;
            this.type = type;
        }
        public void run() {
            try {
                while(true){
                    String url = queue.take();
                    if(FilesUtil.isNotEmpty(url))
                        listener.takeUrl(url,type);
                }
            } catch (InterruptedException e) {
                logger.error("",e);
            }
        }
    }




}
